package com.pan.admin.generator.controller;

import com.gitee.apanlh.annotation.viewresolver.RequestParamVo;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.gitee.apanlh.web.model.vo.ResultVO;
import com.pan.admin.common.annotation.Log;
import com.pan.admin.common.core.controller.BaseController;
import com.pan.admin.common.core.page.TableDataInfo;
import com.pan.admin.common.enums.BusinessType;
import com.pan.admin.generator.constant.ApiGenEnum;
import com.pan.admin.generator.constant.ApiGenFieldTemplateTypeEnum;
import com.pan.admin.generator.context.ApiGenContext;
import com.pan.admin.generator.entity.ApiGenConfigPO;
import com.pan.admin.generator.entity.ApiGenField;
import com.pan.admin.generator.entity.ApiGenWorkBankPO;
import com.pan.admin.generator.entity.vo.ApiGenFieldTemplateVO;
import com.pan.admin.generator.entity.vo.ApiGenFieldWorkBankVO;
import com.pan.admin.generator.service.ApiGenConfigService;
import com.pan.admin.generator.service.ApiGenService;
import com.pan.admin.generator.service.ApiGenWorkBankService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 *  API对接代码生成
 *
 *  @author Pan
 */
@RestController
@RequestMapping("/tool/http/api/gen")
public class ApiGenController extends BaseController {

    @Autowired
    private ApiGenContext apiGenContext;
    @Autowired
    private ApiGenService apiGenService;
    @Autowired
    private ApiGenWorkBankService apiGenWorkBankService;
    @Autowired
    private ApiGenConfigService apiGenConfigService;

    /**
     *  根据字段类型，获取生成字段模板
     */
    @PreAuthorize("@ss.hasPermi('http:api:gen')")
    @GetMapping("/listGenFieldTemplate")
    public ResultVO<Object> listGenFieldTemplate(@RequestParamVo RequestVO requestVO) {
        //  生成类型
        String apiGenType = requestVO.get("apiGenType", String.class);
        ApiGenEnum apiGenEnum = ApiGenEnum.getEnum(apiGenType);
        if (apiGenEnum == null) {
            return ResultVO.fail("非法类型");
        }

        //  获取所需字段类型
        String fieldType = requestVO.get("fieldType", String.class);
        ApiGenFieldTemplateTypeEnum apiGenFieldTemplateTypeEnum = ApiGenFieldTemplateTypeEnum.getEnum(fieldType);
        if (apiGenFieldTemplateTypeEnum == null) {
            return ResultVO.fail("非法字段类型");
        }

        //  获取字段模板
        List<ApiGenField> listApiFieldTemplate = apiGenContext.listFieldTemplate(apiGenEnum, apiGenFieldTemplateTypeEnum);

        //  转换label|value属性值
        List<ApiGenFieldTemplateVO> listApiFieldTemplateVO = ApiGenFieldTemplateVO.ofConvertVO(listApiFieldTemplate);
        return ResultVO.suc(listApiFieldTemplateVO);
    }

    /**
     *  获取我方映射名称词库
     */
    @PreAuthorize("@ss.hasPermi('http:api:gen')")
    @GetMapping("/listMappingNameWorkBank")
    public ResultVO<Object> listMappingNameWorkBank(@RequestParamVo RequestVO requestVO) {
        String fieldName = requestVO.get("fieldName", String.class);
        if (ValidParam.isEmpty(fieldName)) {
            return ResultVO.suc();
        }

        List<ApiGenWorkBankPO> list = apiGenWorkBankService.list(fieldName);
        return ResultVO.suc(ApiGenFieldWorkBankVO.of(list));
    }

    /**
     * 预览代码
     */
//    @PreAuthorize("@ss.hasPermi('http:api:gen')")
//    @GetMapping("/preview/{tableId}")
//    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException {
//        Map<String, String> dataMap = genTableService.previewCode(tableId);
//        return success(dataMap);
//    }

    /**
     * 生成代码（下载方式）
     */
    @PreAuthorize("@ss.hasPermi('http:api:gen')")
    @Log(title = "API代码生成", businessType = BusinessType.GENCODE)
    @PostMapping("/generate")
    public void generate(@RequestParamVo RequestVO requestVO, HttpServletResponse response) throws IOException {
        String body = requestVO.getBody();

        //  获取枚举类型
        String apiGenType = JsonUtils.getNode(body, "apiGenType");
        ApiGenEnum apiGenEnum = ApiGenEnum.getEnum(apiGenType);
        if (apiGenEnum == null) {
            return ;
        }

        byte[] bytes = apiGenService.generate(requestVO, apiGenEnum);
        genCode(response, apiGenType, bytes);
    }

    /**
     *  获取所有配置
     */
    @PreAuthorize("@ss.hasPermi('http:api:gen')")
    @GetMapping("/listConfig")
    public TableDataInfo listConfig(@RequestParamVo RequestVO requestVO) {
        Map<String, Object> params = requestVO.getParams();
        String configName = ClassConvertUtils.toStr(params.get("configName"));

        startPage();
        List<ApiGenConfigPO> list = apiGenConfigService.list(configName);
        return getDataTable(list);
    }

    /**
     *  根据id获取配置-配置导入
     */
    @PreAuthorize("@ss.hasPermi('http:api:gen')")
    @GetMapping("/configImport/{id}")
    public ResultVO<Object> getConfig(@PathVariable("id") Long id) {
        if (ValidParam.isNull(id)) {
            return ResultVO.fail("非法id");
        }
        return ResultVO.suc(apiGenConfigService.get(id));
    }

    /**
     *  生成zip文件
     */
    private void genCode(HttpServletResponse response, String fileName, byte[] data) throws IOException {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        String name = fileName + ".zip";
        response.setHeader("Content-Disposition", "attachment; filename=\"" + name + "\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }
}
